package com.baijiaoxi.common.utils.spring;

import org.springframework.core.ParameterizedTypeReference;
import org.springframework.core.io.FileSystemResource;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;

import java.util.Map;

public class RestTemplateClientImpl implements RestTemplateClient {

    protected RestTemplate restTemplate;
    protected Interceptor interceptor;

    protected RestTemplateClientImpl(RestTemplate restTemplate, Interceptor interceptor) {
        this.restTemplate = restTemplate;
        this.interceptor = interceptor;
    }

    public static RestTemplateClientImpl of(RestTemplate restTemplate) {
        return new RestTemplateClientImpl(restTemplate, new Interceptor() {
            @Override
            public void beforeRequest(HttpHeaders httpHeaders) {

            }
        });
    }

    public static RestTemplateClientImpl of(RestTemplate restTemplate, Interceptor interceptor) {
        return new RestTemplateClientImpl(restTemplate, interceptor);
    }


    public <T> T post(String url, Object json, Class<T> responseType, Map<String, String> headersMap) {
        HttpHeaders headers = createHeaders(headersMap);
        interceptor.beforeRequest(headers);
        HttpEntity httpEntity = createHttpEntity(headers, json);
        return restTemplate.exchange(url, HttpMethod.POST, httpEntity, responseType).getBody();
    }

    public <T> T post(String url, Object json, ParameterizedTypeReference<T> responseType, Map<String, String> headersMap) {
        HttpHeaders headers = createHeaders(headersMap);
        interceptor.beforeRequest(headers);
        HttpEntity httpEntity = createHttpEntity(headers, json);
        return restTemplate.exchange(url, HttpMethod.POST, httpEntity, responseType).getBody();
    }

    public <T> T put(String url, Object json, Class<T> responseType, Map<String, String> headersMap) {
        HttpHeaders headers = createHeaders(headersMap);
        interceptor.beforeRequest(headers);
        HttpEntity httpEntity = createHttpEntity(headers, json);
        return restTemplate.exchange(url, HttpMethod.PUT, httpEntity, responseType).getBody();
    }

    public <T> T put(String url, Object json, ParameterizedTypeReference<T> responseType, Map<String, String> headersMap) {
        HttpHeaders headers = createHeaders(headersMap);
        interceptor.beforeRequest(headers);
        HttpEntity httpEntity = createHttpEntity(headers, json);
        return restTemplate.exchange(url, HttpMethod.PUT, httpEntity, responseType).getBody();
    }

    public <T> T delete(String url, Object json, Class<T> responseType, Map<String, String> headersMap) {
        HttpHeaders headers = createHeaders(headersMap);
        interceptor.beforeRequest(headers);
        HttpEntity httpEntity = createHttpEntity(headers, json);
        return restTemplate.exchange(url, HttpMethod.DELETE, httpEntity, responseType).getBody();
    }

    public <T> T delete(String url, Object json, ParameterizedTypeReference<T> responseType, Map<String, String> headersMap) {
        HttpHeaders headers = createHeaders(headersMap);
        interceptor.beforeRequest(headers);
        HttpEntity httpEntity = createHttpEntity(headers, json);
        return restTemplate.exchange(url, HttpMethod.DELETE, httpEntity, responseType).getBody();
    }

    public <T> T get(String url, Object json, Class<T> responseType, Map<String, String> headersMap) {
        HttpHeaders headers = createHeaders(headersMap);
        interceptor.beforeRequest(headers);
        HttpEntity httpEntity = createHttpEntity(headers, json);
        return restTemplate.exchange(url, HttpMethod.GET, httpEntity, responseType).getBody();
    }

    public <T> T get(String url, Object json, ParameterizedTypeReference<T> responseType, Map<String, String> headersMap) {
        HttpHeaders headers = createHeaders(headersMap);
        interceptor.beforeRequest(headers);
        HttpEntity httpEntity = createHttpEntity(headers, json);
        return restTemplate.exchange(url, HttpMethod.GET, httpEntity, responseType).getBody();
    }

    public <T> T postFile(String url, String filepath, String formParamName, Class<T> responseType, Map<String, String> headersMap) {
        HttpEntity httpEntity = createFileHttpEntity(url, filepath, formParamName, headersMap);
        return restTemplate.exchange(url, HttpMethod.POST, httpEntity, responseType).getBody();
    }

    public <T> T postFile(String url, String filepath, String formParamName, ParameterizedTypeReference<T> responseType, Map<String, String> headersMap) {
        HttpEntity httpEntity = createFileHttpEntity(url, filepath, formParamName, headersMap);
        return restTemplate.exchange(url, HttpMethod.POST, httpEntity, responseType).getBody();
    }

    private HttpEntity createFileHttpEntity(String url, String filepath, String formParamName, Map<String, String> headersMap) {
        HttpHeaders headers = createHeaders(MediaType.MULTIPART_FORM_DATA, headersMap);
        FileSystemResource fileSystemResource = new FileSystemResource(filepath);
        interceptor.beforeRequest(headers);
        MultiValueMap<String, Object> form = new LinkedMultiValueMap<>();
        form.add(formParamName, fileSystemResource);
        HttpEntity httpEntity = createHttpEntity(headers, form);
        return httpEntity;
    }
}
